package com.cndw.kungfu.model.pvp;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.cndw.kungfu.config.Constants;
import com.cndw.kungfu.config.ConstantsDayIntKey;
import com.cndw.kungfu.config.ConstantsIntKey;
import com.cndw.kungfu.config.ConstantsModel;
import com.cndw.kungfu.dao.LiveryDao;
import com.cndw.kungfu.domain.Livery;
import com.cndw.kungfu.domain.Player;
import com.cndw.kungfu.ext.LanguageLib;
import com.cndw.kungfu.ext.TimeProcesser;
import com.cndw.kungfu.model.Context;

@Component
public class LiveryManager {
	@Autowired
	private LiveryDao liveryDao;
	
	/**
	 * 获取个人侍从信息
	 */
	public Livery getFreashLivery(long playerId){
		return getLivery(playerId, true);
	}
	
	private Livery getLivery(long playerId, boolean refreash){
		Livery livery = Context.getDataServer().getLivery(playerId);
		if(livery == null){
			livery =  liveryDao.select(playerId);
			if(livery != null){
				Context.getDataServer().putLivery(playerId, livery);
			}
		}
		if(livery == null){
			livery = new Livery();
			livery.setPlayerId(playerId);
			livery.setCardId(0);
			if(Context.getPlayerServer().getByPlayerId(playerId) != null){
				liveryDao.save(livery);
			}
			Context.getDataServer().putLivery(playerId, livery);
		}
		if(refreash){
			refreash(livery);
		}
		livery.setLastRead(TimeProcesser.getUnixTime());
		return livery;
	}
	
	/**
	 * 更新身份
	 */
	private void refreash(Livery livery){
		if(livery != null){
			int curTime = TimeProcesser.getUnixTime();
			if(livery.getCardId() == 2 &&  curTime >= livery.getEscapeTime()){
				changeCard(livery.getPlayerId(), 0, 0);
			}
			
			if(livery.getCardId() == 1){
				Set<Long> set = livery.getLiverySet();
				if(set != null){
					Iterator<Long> ite = set.iterator();
					while(ite.hasNext()){
						Long l = ite.next();
						Livery tl = getLivery(l, false);
						if(tl.getEscapeTime() <= curTime || tl.getMasterId() != livery.getPlayerId()){
							ite.remove();
							Player tp = Context.getPlayerServer().getByPlayerId(l);
							Context.getMessageServer().recordEvent(livery.getPlayerId(), LanguageLib.get("pvp.livery.title"), LanguageLib.get("pvp.livery.escape", l, tp.getPlayerName(), tp.getVocationId()), Constants.eventTypeLivery);
						}
					}
				}
			}
			
			if(livery.getCardId() == 1 && (livery.getLiverySet() == null || livery.getLiverySet().size() <= 0)){
				changeCard(livery.getPlayerId(), 0, 0);
			}
		}
	}
	
	public void updateLivery(Livery livery){
		if(livery != null){
			liveryDao.update(livery);
		}
	}
	
	private Livery changeCard(long playerId, long masterId, int cardId){
		Livery livery = getLivery(playerId, false);
		synchronized (livery) {
			if(cardId == 0){
				livery.setCardId(cardId);
				livery.setBeginTime(0);
				livery.setEndTime(0);
				livery.setEscapeTime(0);
				livery.setMasterId(0);
				livery.setLiverySet(null);
				livery.setLiveries(null);
			}else if(cardId == 1){
				livery.setCardId(cardId);
				livery.setBeginTime(0);
				livery.setEndTime(0);
				livery.setEscapeTime(0);
				livery.setMasterId(0);
			}else if(cardId == 2){
				livery.setCardId(cardId);
				int curTime = TimeProcesser.getUnixTime();
				livery.setBeginTime(curTime);
				livery.setEndTime(curTime + ConstantsModel.liveryWorkTime);
				livery.setEscapeTime(curTime + ConstantsModel.liveryWorkTime);
				livery.setMasterId(masterId);
				livery.setLiverySet(null);
				livery.setLiveries(null);
			}
		}
		Player player = Context.getPlayerServer().getByPlayerId(playerId);
		player.getDataInfo().intDataSet(ConstantsIntKey.lInact, 0);
		player.getDataInfo().intDataSet(ConstantsIntKey.lMInact, 0);
		return livery;
	}
	
	/**
	 * 增加侍从 手下败将 夺仆之敌
	 * @param livery
	 * @param id
	 * @param type 0 侍从 1 手下败将 2夺仆之敌
 	 */
	public void add(long playerId, long id, int type){
		Livery livery = getFreashLivery(playerId);
		if(type == 0){
			if(livery.getLiverySet().size() >= ConstantsModel.liveryHaveLimit){
				return;
			}
			updateLivery(changeCard(id, playerId, 2));
			livery.getLiverySet().add(id);
			updateLivery(changeCard(playerId, 0, 1));
		}else if(type == 1){
			if(livery.getLoserSet().size() >= ConstantsModel.liveryNumLimit){
				List<Long> list = new LinkedList<Long>(livery.getLoserSet());
				if(list.size() > 0){
					list.remove(0);
					livery.setLoserSet(new LinkedHashSet<Long>(list));
				}
			}
			livery.getLoserSet().add(id);
			updateLivery(livery);
		}else if(type == 2){
			if(livery.getRobEnemySet().size() >= ConstantsModel.liveryNumLimit){
				List<Long> list = new LinkedList<Long>(livery.getRobEnemySet());
				if(list.size() > 0){
					list.remove(0);
					livery.setRobEnemySet(new LinkedHashSet<Long>(list));
				}
			}
			livery.getRobEnemySet().add(id);
			updateLivery(livery);
		}
	}
	
	/**
	 * 移除侍从 手下败将 夺仆之敌
	 * @param livery
	 * @param id
	 * @param type 0 侍从 1 手下败将 2夺仆之敌
 	 */
	public void remove(long playerId, long id, int type){
		Livery livery = getFreashLivery(playerId);
		if(type == 0){
			livery.getLiverySet().remove(id);
			refreash(livery);
			updateLivery(livery);
			updateLivery(changeCard(id, 0, 0));
		}else if(type == 1){
			livery.getLoserSet().remove(id);
			updateLivery(livery);
		}else if(type == 2){
			livery.getRobEnemySet().remove(id);
			updateLivery(livery);
		}
	}
	
	/**
	 * 抢侍从
	 * @param masterLivery 被抢的主人侍从信息
	 * @return 抢到的侍从，主人侍从都逃跑的情况下抢主人
	 */
	public Livery robLivery(Livery masterLivery){
		for(long l : masterLivery.getLiverySet()){
			Livery tl = getFreashLivery(l);
			if(tl.getMasterId() == masterLivery.getPlayerId()){
				return tl;
			}
		}
		return masterLivery;
	}

	/**
	 * 是否可以进行战斗
	 * @param playerId
	 * @param objId
	 * @param type 0抓侍从、1求救、2解救、3反抗 、4夺仆之敌、5雇佣高手
	 * @return
	 */
	public boolean canFight(long playerId, long objId, int type){
		if (playerId == objId) {
			return false;
		}
		if(type == 1 || type == 2){
			Player player = Context.getPlayerServer().getByPlayerId(playerId);
			Player objPlayer = Context.getPlayerServer().getByPlayerId(objId);
			if(player == null || objPlayer == null || player.getUnionId() != objPlayer.getUnionId()){
				return false;
			}
		}
		
		Livery livery = getFreashLivery(playerId);
		Livery objLivery = getFreashLivery(objId);
		if(type == 0){//抓侍从
			if((livery.getCardId() != 0 && livery.getCardId() != 1) || !livery.getLoserSet().contains(objId)){
				return false;
			}
		}else if(type == 1){//求救
			if(livery.getCardId() !=2 || (objLivery.getCardId() != 0 && objLivery.getCardId() != 1)){
				return false;
			}
		}else if(type == 2){//解救
			if((livery.getCardId() != 0 && livery.getCardId() != 1) || objLivery.getCardId() != 2){
				return false;
			}
		}else if(type == 3){//反抗
			if(livery.getCardId() !=2 || objLivery.getCardId() != 1 || livery.getMasterId() != objId){
				return false;
			}
		}else if(type == 4){//夺仆
			if((livery.getCardId() != 0 && livery.getCardId() != 1) || !livery.getRobEnemySet().contains(objId)){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 处理战斗结果
	 * @param playerId
	 * @param objId
	 * @param type 0抓侍从、1求救、2解救、3反抗 、4夺仆、5雇佣高手
	 * @param win 
	 * @param costTime
	 */
	public Map<String, Object> dealFight(long playerId, long objId, int type, boolean win, int costTime){
		Player player = Context.getPlayerServer().getByPlayerId(playerId);
		Livery livery = getFreashLivery(playerId);
		Player objPlayer = Context.getPlayerServer().getByPlayerId(objId);
		Livery objLivery = getFreashLivery(objId);
		String title = LanguageLib.get("pvp.livery.title");
		Map<String, Object> map = new HashMap<String, Object>();
		String msg = "";
		if(type == 0 || type == 4){//抓侍从\夺仆
			if(win){
					if(objLivery.getCardId() == 0){
						add(playerId, objId, 0);
						msg = LanguageLib.get("pvp.liveryfight.catchwin1", objPlayer.getPlayerId(), objPlayer.getPlayerName(),objPlayer.getVocationId());
						Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
						Context.getMessageServer().recordEvent(objId, title, LanguageLib.get("pvp.liveryfight.catchwin2", player.getPlayerId(), player.getPlayerName(), player.getVocationId()), Constants.eventTypeLivery, costTime);
					}else if(objLivery.getCardId() == 1){
						Livery tl = robLivery(objLivery);
						long tId = tl.getPlayerId();
						if(tl != objLivery){
							remove(objId, tId, 0);
							add(objId, playerId, 2);
							Player tPlayer = Context.getPlayerServer().getByPlayerId(tId);
							msg =LanguageLib.get("pvp.liveryfight.robwin1", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId(), tPlayer.getPlayerId(), tPlayer.getPlayerName(), tPlayer.getVocationId());
							Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
							Context.getMessageServer().recordEvent(tId, title, LanguageLib.get("pvp.liveryfight.robwin2", player.getPlayerId(),player.getPlayerName(),player.getVocationId(), objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId()), Constants.eventTypeLivery, costTime);
							Context.getMessageServer().recordEvent(objId, title, LanguageLib.get("pvp.liveryfight.robwin3", player.getPlayerId(), player.getPlayerName(), player.getVocationId(), tPlayer.getPlayerId(), tPlayer.getPlayerName(), tPlayer.getVocationId()), Constants.eventTypeLivery, costTime);
						}else{
							msg = LanguageLib.get("pvp.liveryfight.catchwin1", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
							Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
							Context.getMessageServer().recordEvent(objId, title, LanguageLib.get("pvp.liveryfight.catchwin2", player.getPlayerId(), player.getPlayerName(), player.getVocationId()), Constants.eventTypeLivery, costTime);
						}
						add(playerId, tId, 0);
					}else if(objLivery.getCardId() == 2){
						long masterId = objLivery.getMasterId();
						remove(masterId, objId, 0);
						add(masterId, playerId, 2);
						add(playerId, objId, 0);
						Player masterPlayer = Context.getPlayerServer().getByPlayerId(masterId);
						msg = LanguageLib.get("pvp.liveryfight.robwin1", masterPlayer.getPlayerId(), masterPlayer.getPlayerName(), masterPlayer.getVocationId(), objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
						Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
						Context.getMessageServer().recordEvent(objId, title, LanguageLib.get("pvp.liveryfight.robwin2", player.getPlayerId(), player.getPlayerName(),player.getVocationId(), masterPlayer.getPlayerId(), masterPlayer.getPlayerName(), masterPlayer.getVocationId()), Constants.eventTypeLivery, costTime);
						Context.getMessageServer().recordEvent(masterId, title, LanguageLib.get("pvp.liveryfight.robwin3", player.getPlayerId(), player.getPlayerName(),player.getVocationId(), objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId()), Constants.eventTypeLivery, costTime);
					}
				}else{
					if(type == 0){
						msg = LanguageLib.get("pvp.liveryfight.catchfailed", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
					}else if(type == 4){
						msg = LanguageLib.get("pvp.liveryfight.robfailed1", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
					}
					Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
			}
			player.getDataInfo().getEveryDay().intDataAlter(ConstantsDayIntKey.lCatch, 1);
			map.put("leaveCatch", ConstantsModel.liveryCatchLimit  + player.getDataInfo().getEveryDay().intDataGet(ConstantsDayIntKey.lCatchBuy) - player.getDataInfo().getEveryDay().intDataGet(ConstantsDayIntKey.lCatch));
		}else if(type == 1){//求救
			long masterId = livery.getMasterId();
			Player masterPlayer= Context.getPlayerServer().getByPlayerId(masterId);
			if(win){
				remove(masterId, playerId, 0);
				msg = LanguageLib.get("pvp.liveryfight.callhelpwin1", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId(), masterPlayer.getPlayerId(), masterPlayer.getPlayerName(), masterPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
				Context.getMessageServer().recordEvent(masterId, title, LanguageLib.get("pvp.liveryfight.savewin3", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId(), player.getPlayerId(), player.getPlayerName(),player.getVocationId()), Constants.eventTypeLivery, costTime);
			}else{
				msg = LanguageLib.get("pvp.liveryfight.callhelpfailed", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId(), masterPlayer.getPlayerId(), masterPlayer.getPlayerName(), masterPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
			}
			player.getDataInfo().getEveryDay().intDataAlter(ConstantsDayIntKey.lhelp, 1);
			map.put("leaveCallHelp", ConstantsModel.liveryCallHelpLimit - player.getDataInfo().getEveryDay().intDataGet(ConstantsDayIntKey.lhelp));
		}else if(type == 2){//解救
			long masterId = objLivery.getMasterId();
			Player masterPlayer = Context.getPlayerServer().getByPlayerId(masterId);
			if(win){
				remove(masterId, objId, 0);
				msg = LanguageLib.get("pvp.liveryfight.savewin1", masterPlayer.getPlayerId(), masterPlayer.getPlayerName(), masterPlayer.getVocationId(), objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
				Context.getMessageServer().recordEvent(objId, title, LanguageLib.get("pvp.liveryfight.savewin2", player.getPlayerId(), player.getPlayerName(),player.getVocationId()), Constants.eventTypeLivery, costTime);
				Context.getMessageServer().recordEvent(masterId, title, LanguageLib.get("pvp.liveryfight.savewin3", player.getPlayerId(), player.getPlayerName(),player.getVocationId(), objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId()), Constants.eventTypeLivery, costTime);
			}else{
				msg = LanguageLib.get("pvp.liveryfight.savefailed", masterPlayer.getPlayerId(), masterPlayer.getPlayerName(), masterPlayer.getVocationId(), objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
			}
			player.getDataInfo().getEveryDay().intDataAlter(ConstantsDayIntKey.lSave, 1);
			map.put("leaveSave", ConstantsModel.liverySaveLimit - player.getDataInfo().getEveryDay().intDataGet(ConstantsDayIntKey.lSave));
		}else if(type == 3){//反抗
			if(win){
				remove(objId, playerId, 0);
				msg = LanguageLib.get("pvp.liveryfight.revoltwin1", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
				Context.getMessageServer().recordEvent(objId, title, LanguageLib.get("pvp.liveryfight.revoltwin2", player.getPlayerId(), player.getPlayerName(),player.getVocationId()), Constants.eventTypeLivery, costTime);
			}else{
				msg = LanguageLib.get("pvp.liveryfight.revoltfailed", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
			}
			player.getDataInfo().getEveryDay().intDataAlter(ConstantsDayIntKey.lRevolt, 1);
			map.put("leaveRevolt", ConstantsModel.liveryRevoltLimit + player.getDataInfo().getEveryDay().intDataGet(ConstantsDayIntKey.lRevoltBuy) - player.getDataInfo().getEveryDay().intDataGet(ConstantsDayIntKey.lRevolt));
		} else if(type == 5) {//雇佣高手
			if(win) {
				remove(objId, playerId, 0);
				msg = LanguageLib.get("pvp.hireguard.guardwin1", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
				Context.getMessageServer().recordEvent(objId, title, LanguageLib.get("pvp.hireguard.guardwin2", player.getPlayerId(), player.getPlayerName(),player.getVocationId()), Constants.eventTypeLivery, costTime);
			} else {
				msg = LanguageLib.get("pvp.hireguard.guardfailed", objPlayer.getPlayerId(), objPlayer.getPlayerName(), objPlayer.getVocationId());
				Context.getMessageServer().recordEvent(playerId, title, msg, Constants.eventTypeLivery, costTime);
			}
		}
		map.put("msg", msg);
		map.put("cardId",  livery.getCardId());
		return map;
	}
}
